﻿using KeraLua;
using Microsoft.Extensions.Logging;
using NLua;
using System.Security;
using System.Text;
using System.Threading.Tasks;
using Lua = NLua.Lua;

namespace LuaConsole
{
    public class LuaMaster : IDisposable
    {
        private readonly ILogger<LuaMaster> logger;
        private Lua state = new Lua();
        private Dictionary<string, object> data = new Dictionary<string, object>();
        public bool IsExe = false;
        public object this[string item]
        {
            get
            {
                object t = null;
                data.TryGetValue(item, out t);
                return t;
            }
            set
            {
                if (!data.TryAdd(item, value))
                {
                    data[item] = value;
                }
                this.state[item] = value;
            }
        }
        public LuaMaster(ILogger<LuaMaster> logger)
        {
            this.logger = logger;
            state.State.Encoding = Encoding.UTF8;
            Type type = this.GetType();
            state.LoadCLRPackage();
            state.RegisterFunction("print", type.GetMethod("Print"));
            state.RegisterFunction("Lua_PrtMsg", type.GetMethod("Print"));
            state.RegisterFunction("Info", type.GetMethod("Print"));
            state.RegisterFunction("FileWrite", type.GetMethod("FileWriteData"));
            state.RegisterFunction("Delay", type.GetMethod("Sleep"));
            state.RegisterFunction("Lua_Sleep", type.GetMethod("Sleep"));
            state.RegisterFunction("ClearMsg", type.GetMethod("ClearPrint"));
            state.SetDebugHook(KeraLua.LuaHookMask.Line, 0);
            state.DebugHook += _state_DebugHook;
        }

        private void _state_DebugHook(object? sender, NLua.Event.DebugHookEventArgs e)
        {
            ExeStatusDebugHook();
            //logger.LogInformation("Lua Run Line:{nums}", e.LuaDebug.CurrentLine);
        }

        public static Action<object>? PrintMsg;
        public static Action ClearMeg;

        public Lua Master { get { return state; } set { state = value; } }


        public static void Print(object obj)
        {

            if (PrintMsg is null)
            {
                PrintMsg = Console.WriteLine;
            }
            LuaMaster.PrintMsg?.Invoke(obj);
        }

        public static void ClearPrint()
        {
            LuaMaster.ClearMeg?.Invoke();
        }

        public static void Sleep(int value)
        {
            Thread.Sleep(value);
        }
        public static void FileWriteData(string path, string data, string mode)
        {
            using (var file = File.Open(path, FileMode.Append))
            {
                using (var str = new StreamWriter(file))
                {
                    str.WriteLine(data);
                }
            }
        }

        private void ExeStatusDebugHook()
        {
            Exit();
            Thread.Sleep(0);
        }

        private void Exit()
        {
            if (!IsExe)
            {
                ModelClose();
                state.State.Error("终止当前任务");
            }
        }

        public void Run(string data)
        {
            IsExe = true;
            state.DoString(data);
        }

        private void ModelClose()
        {
            foreach (var dic in data)
            {
                var typc = dic.Value.GetType();
                if (typc.Name == "SerialPort" || typc.Name == "ForceTransducers" || typc.Name == "PowerSCPI")
                {
                    typc.GetMethod("Close").Invoke(dic.Value, new object[0]);
                }
            }
        }
        public void Dispose()
        {
            ((IDisposable)state).Dispose();
        }
    }
}
